#include<errno.h>
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>



//#include "mk_util.h"
#include "print_log.h"
//#include "shell_cmd.h"
//#include "user_log.h"

#include "file_util.h"




/************************
copy file
***************************/
int copy_file(const char *dst_name, const char *src_name)
{
	FILE *fp_dst = NULL;
	FILE *fp_src = NULL;
	char *buf = NULL;
	int ret = -1;

	log_debug("copy %s %s", dst_name, src_name);

	int len = read_file_len(src_name);

	fp_dst = fopen(dst_name, "wb");
	if(fp_dst == NULL) {
		goto _err_exit;
	}
	fp_src = fopen(src_name, "r");
	if(fp_src == NULL) {
		goto _err_exit;
	}

	buf = malloc(len);
	if(buf == NULL) {
		goto _err_exit;
	}

	if (fread(buf, len, 1, fp_src) <= 0) {
		goto _err_exit;
	}
	

	if(fwrite(buf, len, 1,  fp_dst) < 0) {
		goto _err_exit;
	}
	ret = 0;

	

_err_exit:
	if(fp_dst) {
		fclose(fp_dst);
	}
	if(fp_src) {
		fclose(fp_src);
	}
	if(buf) {
		free(buf);
	}
	return ret;		
}


/*********************************************************
read file len  读取文件长度
****************************************************/
size_t read_file_len(const char *file_name)
{
	
	struct stat statbuf={0};

	stat(file_name, &statbuf);

	size_t size=statbuf.st_size;

	return size;
	
}



/**************************************************
**************************************************/

/***
返回 
NULL:  无文件
malloc:  文件列表
***/
int get_total_file(const char *path)
{
	DIR *dir;        
	struct dirent *pDir; 
	int file_cnt = 0;
	
	if((dir = opendir(path)) == NULL){                
		printf("no this path:%s\n", path);                
		return 0;        
	}         
	while((pDir = readdir(dir)) != NULL){                
		if(strcmp(pDir->d_name,".")==0 || strcmp(pDir->d_name,"..")==0){
			continue;                
		}else if(pDir->d_type == 8){ // 文件                     
			file_cnt ++;
		}
		else if(pDir->d_type == 10){                        
			continue;                
		}else if(pDir->d_type == 4){ // 子目录  
		#if 0
			char name[64];
			sprintf(name, "%s/%s/", path, pDir->d_name);
			file_cnt += get_total_file(name);
		#else
			file_cnt ++;
		#endif
		}   
	}        
	closedir(dir);        

	return file_cnt;
	
}


/******************************************************************
function: list_dir_file() 读取文件夹里全部文件和子目录
param: *path
       *pfile_num : 返回文件数量
       
return *dir_out:   存放文件信息结构体缓冲区
*******************************************************************/
dirent_t *list_dir_file(const char *path, int *pfile_num)
{
	print_me();
	
	dirent_t *dir_out = NULL;
	
	DIR *dir;        
	struct dirent *pDir; 
	int file_cnt = 0;
	
	if((dir = opendir(path)) == NULL){                
		printf("no this path:%s\n", path);                
		//return NULL;   
		goto _exit;
	}         

	// calc file number
	while((pDir = readdir(dir)) != NULL){     
		//printf("first dir: %s\n", pDir->d_name);
		if(strcmp(pDir->d_name,".")==0 || strcmp(pDir->d_name,"..")==0){
			continue;                
		}
		else if((pDir->d_type == 8)||(pDir->d_type == 4)){ // 文件   or     子目录                    
			file_cnt ++;
		}
	}        
	

	printf("path=%s, filecnt=%d\n", path, file_cnt);

	if(file_cnt == 0) {
		*pfile_num = 0;
		//printf("1111111\n");
		goto _exit;

	}

	int out_len = file_cnt * sizeof(dirent_t);
	dir_out = (dirent_t *)malloc(out_len);
	if(dir_out == NULL) {
		//printf("2222222\n");
		goto _exit;
	}
	memset(dir_out, 0, out_len);

	closedir(dir); 
	dir = NULL;


	if((dir = opendir(path)) == NULL){				  
		printf("no this path2:%s\n", path);				  
		goto _exit;
	}		 

	
	dirent_t *out_dst = dir_out;
	*pfile_num = file_cnt;
	while((pDir = readdir(dir)) != NULL){  
		//printf("seccc dir: %s\n", pDir->d_name);
		if(strcmp(pDir->d_name,".")==0 || strcmp(pDir->d_name,"..")==0){
			continue;                
		}
		else if((pDir->d_type == 8)||(pDir->d_type == 4)){ // 文件   or     子目录                    
			if (file_cnt > 0) { 
				strcpy(out_dst->d_name, pDir->d_name);
				out_dst->d_type = pDir->d_type;
				out_dst ++;
				file_cnt --;
			}
			
		}
	} 

_exit:	
	if(dir) {
		closedir(dir);    
	}

	return dir_out;
}

int list_dir_file_old(const char *path, dirent_t *dir_out, int max_file)
{
	DIR *dir;        
	struct dirent *pDir; 
	int file_cnt = 0;
	
	if((dir = opendir(path)) == NULL){                
		printf("no this path:%s\n", path);                
		return 0;        
	}         
	while((pDir = readdir(dir)) != NULL){                
		if(strcmp(pDir->d_name,".")==0 || strcmp(pDir->d_name,"..")==0){
			continue;                
		}else if((pDir->d_type == 8)||(pDir->d_type == 4)){ // 文件   or     子目录                    
			if (file_cnt <  max_file) { 
				strcpy(dir_out->d_name, pDir->d_name);
				dir_out->d_type = pDir->d_type;
				dir_out ++;
			}
			file_cnt ++;
		}
	}        
	closedir(dir);        

	return file_cnt;
}

#if 0
void test_list_dir()
{
	dirent_t *pdir;
	pdir = (dirent_t *)malloc(100*sizeof(dirent_t));
	if (pdir == NULL) {
		printf("malloc error\n");
		exit(0);
	}

	list_dir_file("/home/smgateway/upgrade/", pdir, 100);
	

	free(pdir);
	exit(0);
}
#endif


/***
返回 
0，成功
1， 失败

***/
int tar_dir(char *tar_file_name, int len, const char *path)
{

	return -1;
}


/***
返回 
0，成功
1， 无此文件
2， 删除失败
***/
int delete_file(const char *filename)
{

	return remove(filename);
}

/***
返回 
0，成功
1， 无此文件路径
2， 删除失败
***/
int delete_dir(const char *path)
{
	int ret = remove(path);
	if (ret) {
		perror("remove");
	}
	return ret;
}

/****
清空目录里的所有文件
****/
int empty_dir(const char *path) 
{
	printf("empty dir:%s\n", path);
}

int get_my_path(char *path, int size)
{
	//获取当前程序绝对路径
	int cnt = readlink("/proc/self/exe", path, size);
	if (cnt < 0 || cnt >= size) {
	    printf("***Error***\n");
	    return -1;
	}
	//获取当前目录绝对路径，即去掉程序名
	int i;
	for (i = cnt; i >=0; --i)
	{
	    if (path[i] == '/')
	    {
	        path[i+1] = '\0';
	        break;
	    }
	}
	//printf("current absolute path:%s\n", path);
	return 0;
}

#if 0
vector<string> getfiles(string strCurrentDir)
{        vector<string> vFiles; // 存放文件名们        
	DIR *dir;        
	struct dirent *pDir;        
	if((dir = opendir(strCurrentDir.c_str())) == NULL){                
		cout << "open dir Faild" << endl;                
		exit(1);        
		}         
	while((pDir = readdir(dir)) != NULL){                
		if(strcmp(pDir->d_name,".")==0 || strcmp(pDir->d_name,"..")==0){
			continue;                
		}else if(pDir->d_type == 8){ // 文件                        
			vFiles.push_back(strCurrentDir + "/" + pDir->d_name);                
		}else if(pDir->d_type == 10){                        
			continue;                
		}else if(pDir->d_type == 4){ // 子目录                        
			string strNextdir = strCurrentDir + "/" + pDir->d_name;
			vector<string> ss = getfiles(strNextdir); 
			vFiles.insert(vFiles.end(),ss.begin(),ss.end()); // 组合到一起。   
		}        
	}        
	closedir(dir);        
	// 排下序 - 根据自己喜好        
	sort(vFiles.begin(), vFiles.end());        
	return vFiles;
}

int main()
{        
	char basePath[100]; // 当前目录        
	memset(basePath, '\0', sizeof(basePath));        
	getcwd(basePath, 999);        
	printf("主目录: %s\n",basePath);         
	vector<string> files=getfiles(basePath);        
	for (size_t i=0; i<files.size(); i++)        {
		cout<<files[i]<<endl;        
	}        
	return 0;
}
#endif



int read_total_file(FILE *fp, void *pdst, int dst_size)
{
	fseek(fp, 0, SEEK_END);
	int len = ftell(fp);
	if (len<=dst_size) {
		rewind(fp);
		fread(pdst, 1, len, fp);
		return len;
	}
	else {
		printf("read file buf too small\n");
		return -1;
	}
}

/******************************************************
function : read_file_all_data()  读整个文件数据, 只适合小文件
param ：file_name
        *pout_len: 文件数据字节数
return:  *buf :  文件数据指针      ，  返回数据指针， 使用方用完后释放
         当文件太大， 分配不了空间，返回空指针， 但是*pout_len仍然是文件长度
*************************************************/
unsigned char  *read_file_all_data(const char *file_name, INOUT size_t *pout_len)
{
	// len
	size_t file_len = read_file_len(file_name);
	if(file_len <= 0) {
		log_debug("file len <= 0 : %s\n", file_name);
		return NULL;
	}

	if(pout_len) {
		*pout_len = file_len;
	}
	
	FILE *fp = fopen(file_name,"r");
	if(fp == NULL) {
		//log_debug("open file:%s error", file_name);
		return NULL;
	}


	unsigned char *buf = malloc(file_len);
	if(buf ) {
		int read_len = fread(buf, 1, file_len, fp);
		if(pout_len) {
			*pout_len = read_len;    //  重写一次真实文件数据大小
		}
		if(read_len == 0) {
			free(buf);
			buf = NULL;
		}
	}
	else {
		perror("malloc read_file_all_data");
	}
		
_err_exit:
	if(fp) {
		fclose(fp);
		fp = NULL;
	}
	
	return buf;
}
int write_new_file_data(const char *filename, const unsigned char *pdat, int dat_len)
{
	FILE *fp = fopen(filename, "wb");
	if (fp == NULL) {
		printf("open  new file  %s error\n", filename);
		return -1;
	}
	fwrite(pdat, 1, dat_len, fp);
	fclose(fp);
	return 0;
}
int create_mult_dir( char *sPathName )  
{  
    //char DirName[256];    
    int res = 0;
	int i;
    int len = strlen(sPathName);
	char *DirName=(char*)malloc(len+10);
	if (DirName == NULL) {
		perror("dir malloc");
		return -1;
	}
	
    strcpy(DirName,sPathName);      
         
    if(DirName[len-1]!='/')   {   
    	strcat(DirName,"/");   
    }
    len = strlen(DirName);      
    for(i=1;i<len;i++)      
    {      
        if(DirName[i]=='/')      
        {      
            DirName[i] = 0;      
            if(access(DirName, 0/*NULL*/) != 0)      
            {      
                if(mkdir(DirName,0777) == -1)      
                {       
                    perror("mkdir error");       
                    res = -1;
					break;
                }      
            }    
            DirName[i] = '/';      
         }      
  }        

	free(DirName);
	DirName = NULL;
	
  return res;      
}  

/***
/mnt/UDISK/gw_plc/data/ota/gw/log_mem.sh.bin#1.0.0
---> log_mem.sh.bin#1.0.0
从全路径字符串里提取出单纯的文件名
***/
const char *get_pure_filename_from_fullname(const char *full_name)
{
	//int i;
	//for(i=0; )
}



/***
./boss/
./bill/
./log/8376161000000001
./log/SDN1000000000001
****/
void init_work_dir()
{
	DIR *pdir;
	int res;

	//create_mult_dir(BOSS_DIR);
	//create_mult_dir(BILL_DIR);
	//create_mult_dir(LOG_DIR);
    //create_mult_dir(CSV_DIR);
    //create_mult_dir(DB_DIR);

}


int create_pile_dir(const char *pile_id)
{
#if 0
	int len = strlen(pile_id);
	if (len > 32) {
		printf("pile id error\n");
		return -2;
	}
	char *s_dir=(char*)malloc(200);
	if (s_dir == NULL) {
		perror("pile dir malloc");
		return -1;
	}

	strcpy(s_dir, LOG_DIR);
	strcat(s_dir, pile_id);

	create_mult_dir(s_dir);

	free(s_dir);
#endif	
	return 0;
}


int exec_file(const char *file_cmd, char *buf, int len)
{
	int ret = -1;
	FILE *fp;


	printf("exec file: %s\n", file_cmd);

	fp = popen(file_cmd, "r");
	if(fp == NULL) {
		printf("exec: %s error!\n", file_cmd);
		return -1;
	}

    //printf("===============\n");
	//printf("get: %s\n", buf);
	//printf("#################\n");

	while(NULL!=fgets(buf, len, fp)) {
		printf("read out:\n");
            printf("%s",buf);  
		ret = 0;

    }
	printf("\n");
	
    pclose(fp);  

	return ret;

}

#if 0
/******************************************
取出第N项
******************************************/
int get_seg_str(const char *psrc, int seg, char *pdst, int dst_len)
{

	//printf("serach seg:%d in %s\n", seg, psrc);

	const char *pt = psrc;
	int len = 0;
	for(int i=1; i<=seg; i++) {
		
		pt = pt+len;
		memset(pdst, 0, dst_len);
		while(*pt == 0x20) {
			pt++;
		}
		sscanf(pt, "%s", pdst);
		len = strlen(pdst);
		//printf("loop get i=%d, str=%s, len=%d\n", i, pdst, len);
		
	}
	

	//printf("now pdst=%s\n", pdst);
	
	
	
_err_exit:
	return 0;

}

int exec_file_find_str(const char *file_cmd, const char *str_find, int seg, char *buf, int len)
{
	int ret = -1;
	FILE *fp;


	printf("find rsp:'%s' from exec file: '%s'\n", str_find, file_cmd);
	

	fp = popen(file_cmd, "r");
	if(fp == NULL) {
		printf("exec: %s error!\n", file_cmd);
		return -1;
	}

 
	char rsp_buf[128]={0};
	int cnt = 0;
	while(NULL!=fgets(rsp_buf, len, fp)) {
		//printf("cnt=%d, read out:\n", cnt++);
        //printf("%s",rsp_buf);  

		if(strstr(rsp_buf, str_find) != NULL) {	


		
			strncpy(buf, rsp_buf, len);
			ret = 0;
			printf("get it: %s\n", buf);



			get_seg_str(rsp_buf, seg, buf, len);

			//printf("buf=%s\n", buf);
			
			break;
		}
		else {
			//printf("not include:%s\n", str_find);
		}
		memset(rsp_buf, 0, sizeof(rsp_buf));
    }
	printf("\n");
	
    pclose(fp);  

	return ret;

}
#endif



int is_null_line(char head)
{
	return (head==0x0d || head==0x0a );
}

int get_file_line_number(FILE *fp, char *dat_buf, int len)
{
	int line_number = 0;
	while((fgets(dat_buf, len,fp))!=NULL)   {
		if(!is_null_line(*dat_buf))
		{
			line_number ++;	
		}
	}

	return line_number;
}

/***********************************************
截取出文件扩展名： 首个'.'后面的所有字符。
*************************************************/
const char *get_file_name_ext(const char *filename)
{
	const char *pout = filename;
	while(*pout) {
		if(*pout == '.') {
			return pout;
		}
		pout++;
	}
	return NULL;
}

